#ifndef __VEHICLE_H__
#define __VEHICLE_H__

#include "process.h"

#define PID_MAX_SIZE                        16
#define SUPPORTED                           TRUE
#define UNSUPPORTED                         FALSE

typedef enum {
    VEHICLE_TOYOTA,
    VEHICLE_GM,
    VEHICLE_VAG,
    VEHICLE_LAVIDA,
    VEHICLE_HAVAL,
    VEHICLE_HYUNDAI,
    VEHICLE_SENOVA,
    VEHICLE_EOBD,
} VehicleTypeEnum;

typedef enum {
    CODE_ENGINE,
    CODE_AT,
    CODE_ABS,
    CODE_SRS,
    CODE_BCM,
    CODE_IPC,
    CODE_EPS,
    CODE_AC,
    CODE_TPMS,
    //total size of code
    CODE_SIZE
} FaultCodeType;

#define CODE_MAX_SIZE                       32

typedef struct {
    uint8_t type;
    uint16_t codes[CODE_MAX_SIZE];
    uint8_t count;
} FaultCodeItem;

typedef struct {
    uint8_t id;
    uint8_t pid;
    uint8_t offset;
    uint8_t size;
    uint8_t support;
} PidMap;

#define SUPPORT_CONTROL_WINDOW              1 << 0
#define SUPPORT_CONTROL_DOOR                1 << 1
#define SUPPORT_CONTROL_LIGHT               1 << 2
#define SUPPORT_CONTROL_SUNROOF             1 << 3
#define SUPPORT_CONTROL_TRUNK               1 << 4
#define SUPPORT_CONTROL_FINDCAR             1 << 5
#define SUPPORT_CONTROL_IMMOLOCK            1 << 6

typedef struct {
    uint32_t support;
    void (*control_window)(uint8_t state);
    void (*control_door)(uint8_t state);
    void (*control_light)(uint8_t state);
    void (*control_sunroof)(uint8_t state);
    void (*control_trunk)(uint8_t state);
    void (*control_findcar)(uint8_t state);
    void (*control_immolock)(uint8_t state);
} VehicleCtrlOps;

typedef struct {
    uint8_t id;
    uint8_t updated;
    uint8_t data[PID_MAX_SIZE];
    uint8_t len;
} ResultData;

typedef struct {
    uint8_t updated;
    uint8_t code[17];
} VinCode;

typedef struct {
    uint8_t need_update_size;
    ResultData data[ENG_DATA_SIZE];
} EngineDataMap;

typedef struct {
    uint8_t need_update_size;
    uint8_t size;
    ResultData data[BCM_DATA_SIZE];
} BcmDataMap;

typedef struct {
    ResultData data[IPC_DATA_SIZE];
} IpcDataMap;

typedef struct {
    uint8_t (*check_engine_on)(void);
    void (*get_rpm)(uint16_t *rpm);
    void (*process_vin_code)(VinCode *code);
    void (*process_eng_data)(EngineDataMap *map);
    void (*process_bcm_data)(BcmDataMap *map);
    void (*process_ipc_data)(IpcDataMap *map);
    void (*process_bcm_door_data)(BcmDataMap *map);
    void (*process_bcm_window_data)(BcmDataMap *map);
    void (*keepalive)(void);
    uint8_t (*clear_fault_code)(uint8_t type);
    void (*get_fault_code)(uint8_t type, FaultCodeItem *item);
} VehicleProcessOps;

typedef struct {
    uint8_t inited;
    uint8_t engine_on;
    uint8_t vehicle_type;
    VehicleProcessOps *processOps;
    VehicleCtrlOps *ctrlOps;
    OS_MUTEX lock;
} Vehicle;

void vehicle_init(void);
uint8_t vehicle_check_engine(void);
void vehicle_engine_trigger(void);
void vehicle_task(void *unused);
void vehicle_control_task(void *unused);
void vehicle_setup(VehicleTypeEnum type);
uint8_t vehicle_get_type(void);
void vehicle_set_engine_on(uint8_t on);

void vehicle_lock(void);
void vehicle_unlock(void);
void vehicle_rx_timer_callback(void *p_arg);
void vehicle_rx_start_timer(uint16_t timeout);
void vehicle_rx_stop_timer(void);
uint8_t vehicle_can_session(CanTxMsg *txMsg, CanRxMsg *rxMsg);
uint8_t vehicle_can_recv(CanRxMsg *rxMsg);

void dump_eng_result(EngineDataMap *dataMap);
void dump_bcm_result(BcmDataMap *dataMap);
void dump_ipc_result(IpcDataMap *dataMap);
int16_t index_of_buf(uint8_t *buf, uint8_t size, uint8_t value);

#endif
